package TP6;

import java.util.ArrayList;

/**
 * Clase que fue pensada para administrar la simulación.
 */
public class Simulador {
   
    private static double tiempo100=60;
    private static double tiempo70=52.86;
    private static double tiempo50=46.12;
    private double alfa=0.049942;
    private int logs;
    
    
    private final double tiempoSimulacion;
    private static double atencionClienteMinimo=2.5;
    private static double atencionClienteMaximo=3.5;
    private static double llegadaClienteMinimo=2.5;
    private static double llegadaClienteMaximo=3.0;
    private static double llegadaRepositorMaxima=(12*60);
    private static double llegadaRepositorMinima=(10*60);
    private VectorEstado actual;
    
    
    
    public static double calcularLlegadaRepositor(double rnd) {
        return (rnd * (llegadaRepositorMaxima - llegadaRepositorMinima) + llegadaRepositorMinima);
    }

    public static double calcularAtencionCliente(double rnd) {
        return (rnd * (atencionClienteMaximo - atencionClienteMinimo)) + atencionClienteMinimo;
    }
    
    public static double calcularLlegadaCliente(double rnd){   return (rnd * (llegadaClienteMaximo - llegadaClienteMinimo)) + llegadaClienteMinimo;
    }

    public static double calcularDiscoLleno(double porcentajeDiscoLleno) {
        double res=0;
        if(porcentajeDiscoLleno==0.5) res=Euler.euler(0.05, 0.0, 0.5);
        if(porcentajeDiscoLleno==0.7) res=Euler.euler(0.05, 0.0, 0.7);
        if(porcentajeDiscoLleno==1) res=Euler.euler(0.05, 0.0, 1.0);
      
        return res;         
    }
    
    public static void setAtencionClienteMaximo(double antencionClienteMaximo) {
        Simulador.atencionClienteMaximo = antencionClienteMaximo;
    }

    public static void setAtencionClienteMinimo(double atencionClienteMinimo) {
        Simulador.atencionClienteMinimo = atencionClienteMinimo;
    }

    public static void setLlegadaClienteMaximo(double llegadaClienteMaximo) {
        Simulador.llegadaClienteMaximo = llegadaClienteMaximo;
    }

    public static void setLlegadaClienteMinimo(double llegadaClienteMinimo) {
        Simulador.llegadaClienteMinimo = llegadaClienteMinimo;
    }

    public static void setLlegadaRepositorMaxima(double l) {
        llegadaRepositorMaxima = l;
    }

    public static void setLlegadaRepositorMinima(double l) {
       llegadaRepositorMinima = l;
    }

    /**
     * Recibe sólo el tiempo de simulación, y configura el resto de los
     * parámetros de tiempo tal y como dice el enunciado dado.
     *
     * @param tiempoSimulacion tiempo total de simulación
     */
    public Simulador(double tiempoSimulacion) {
        this.tiempoSimulacion = tiempoSimulacion;
        
    }

    /**
     * Recibe el tiempo de simulación y el resto de los parámetros configurables
     * de tiempo.
     *
     * @param tiempoSimulacion tiempo total de simulación, en minutos.
     * @param llegadaClienteBase el mínimo del intervalo
     * de tiempos de llegada de los clientes al expendedor, en minutos.
     * @param atencionClienteMaximo el máximo del intervalo
     * de tiempos de llegada de los clientes al expendedor, en minutos.
     * @param tiempoParaDespacharClienteLimiteInferior el mínimo del intervalo
     * de tiempos que tarda el expendedor en despachar a los clientes, una vez
     * que empiezan a ser atendidos, en minutos.
     * @param tiempoParaDespacharClienteLimiteSuperior el máximo del intervalo
     * de tiempos que tarda el expendedor en despachar a los clientes, una vez
     * que empiezan a ser atendidos, en minutos.
     * @param llegadaRepositorMaxima el mínimo tiempo entre
     * llegadas del repositor, en minutos.
     * @param llegadaRepositorMinima el máximo tiempo entre
     * llegadas del repositor, en minutos.
     * @param tiempoMinimoReposicion tiempo mínimo de reposición, en minutos.
     * @param tiempoReposicionPorLata tiempo adicional que tarda el repositor,
     * por lata, en minutos.
     * @param tiempoMinimoAdicionalCambio tiempo mínimo que tarda el repositor
     * en caso de tener que cambiar los stocks iniciales de las gaseosas, en
     * minutos.
     * @param tiempoPorLataRetirada tiempo adicional que tarda el repositor, por
     * lata, en minutos.
     */
//    public Simulador(double tiempoSimulacion, double tiempoEntreLlegadasClientesLimiteInferior, double tiempoEntreLlegadasClientesLimiteSuperior, double tiempoParaDespacharClienteLimiteInferior, double tiempoParaDespacharClienteLimiteSuperior, double tiempoEntreLlegadasRepositorLimiteInferior, double tiempoEntreLlegadasRepositorLimiteSuperior, double tiempoMinimoReposicion, double tiempoReposicionPorLata, double tiempoMinimoAdicionalCambio, double tiempoPorLataRetirada) {
//        this.tiempoSimulacion = tiempoSimulacion;
//        this.llegadaClienteBase = tiempoEntreLlegadasClientesLimiteInferior;
//        this.llegadaClienteMaximallegadaClienteMaxima = tiempoEntreLlegadasClientesLimiteSuperior;
//        this.tiempoParaDespacharClienteLimiteInferior = tiempoParaDespacharClienteLimiteInferior;
//        this.tiempoParaDespacharClienteLimiteSuperior = tiempoParaDespacharClienteLimiteSuperior;
//        this.llegadaRepositorMaxima = tiempoEntreLlegadasRepositorLimiteInferior;
//        this.llegadaRepositorMinima = tiempoEntreLlegadasRepositorLimiteSuperior;
//        this.tiempoMinimoReposicion = tiempoMinimoReposicion;
//        this.tiempoReposicionPorLata = tiempoReposicionPorLata;
//        this.tiempoMinimoAdicionalCambio = tiempoMinimoAdicionalCambio;
//        this.tiempoPorLataRetirada = tiempoPorLataRetirada;
//    }
//
    /**
     * realiza la simulacion y guarda en un ArrayList los vectorEstado 
     * que tiene que imprimir
     *
     * @return Lista de vectorEstado que se imprimen
     * @param minutosDesde tiempo de simulacion que se empieza a imprimir el vector
     * @param minutosHasta tiempo de simulacion hasta donde se imprime el vector
     */
    public ArrayList<VectorEstado> simular(double minutosDesde, double minutosHasta) {
        ArrayList<VectorEstado> datos = new ArrayList<VectorEstado>();

        Expendedor expendedor = new Expendedor(40, 20, 20, 80);
        actual = new VectorEstado(expendedor);

        actual.iniciarVector();

        if (actual.getReloj() >= minutosDesde) {
            datos.add(actual);
        }

        while (calcularProximoVector()) {

            if (actual.getReloj() > minutosDesde && actual.getReloj() < minutosHasta) {
                datos.add(actual);
            }

        }
        return datos;
    }

    public boolean calcularProximoVector() {
        boolean seguirCalculando = true;

        VectorEstado nuevo = new VectorEstado(actual);
        nuevo.setReloj(actual.getRelojEventoProximo());
        nuevo.setEvento(actual.eventoSiguiente);
        nuevo.getEvento().calcularProximaLlegada(nuevo);
        actual = nuevo;


        if (actual.getReloj() >= tiempoSimulacion) {
            seguirCalculando = false;
        }

        //System.out.println(actual.toString());

        return seguirCalculando;

    }

    public ArrayList<Cliente> obtenerClientes() {
        return actual.getExpendedor().getClientes();
    }

    public VectorEstado next() {
        calcularProximoVector();
        return actual;
    }

    public int[] datosSimulacion() {
        int[] datos = new int[7];
        datos[0] = actual.getContadorPersonasAtendidas();
        datos[1] = actual.getContadorPersonasNoConsiguieronGaseosaYseFueron();
        datos[2] = actual.getContadorPersonasNoConsiguieronGaseosaDeseada();
        datos[3] = actual.getContadorDeReposiciones();
        datos[4] = actual.getContadorDeCambiosA();
        datos[5] = actual.getContadorDeCambiosB();
        datos[6] = actual.getContadorDeCambiosC();
        return datos;
    }
}
